#ifndef __COMMON_H__
#define __COMMON_H__

#include <vector>
#include <algorithm>

// 记录每次测试的setup和solve时间，以及迭代次数
struct TEST_TIME {
    double t_trans = 0.0;// host <-> device 之间的传输时间
    double t_setup = 0.0;
    double t_solve = 0.0;
    int iter = 0;
    // 用于将总时间从低到高排序
    bool operator < (const TEST_TIME & b) const {
        return (t_trans + t_setup + t_solve) < (b.t_trans + b.t_setup + b.t_solve);
    }
    double sum() {
        return t_trans + t_setup + t_solve;
    }
};

template<typename idx_t, typename data_t>
void matinv_row(const int nrows, data_t * A, const int lda) {
    // 构造单位阵
	data_t* E = new data_t [nrows * nrows];
    memset(E, 0.0, sizeof(data_t) * nrows * nrows);
    #pragma GCC unroll (4)
    for (idx_t r = 0; r < nrows; r++)
        E[r * nrows + r] = 1.0;
    // 初等行变换
    for (idx_t i = 0; i < nrows; i++) {
        data_t tmp = A[i * lda + i];
        #pragma GCC unroll (4)
        for (idx_t j = 0; j < nrows; j++) {
            A[j * lda   + i] /= tmp;
            E[j * nrows + i] /= tmp;
        }
        // 此时A(i,i)为1，利用这个1消掉上面、下面的行中该列的非零元
        for (idx_t k = 0; k < nrows; k++) {
            if (k == i) continue;
            data_t tmp = A[i * lda + k];
            #pragma GCC unroll (4)
            for (idx_t j = 0; j < nrows; j++) {
                A[j * lda   + k] -= tmp * A[j * lda   + i];
                E[j * nrows + k] -= tmp * E[j * nrows + i];
            }
        }
    }
	// 拷回
	for (idx_t j = 0; j < nrows; j++)
	for (idx_t i = 0; i < nrows; i++)
		A[j * lda + i] = E[j * nrows + i];
    delete[] E;
}

#endif